#include "FractalTree.h"

FractalTree::FractalTree(){
	Reset();

}

void FractalTree::Reset(){
mName = new string("Explosion");
	mExpandRate = 1.0f;// 2.0f* Random();
	mDecayRate = 1.2f;//* Random() + 0.4f;
	mPower = 2.0f;// * Random();
	mSpawnScale = 0.8f;//0.2f* Random() + 0.69f;
	ini = false;
	mNodes= new vector<ExplosionNode*> ();
	mTemp = new vector<ExplosionNode*> ();
	mDone= false;
	mDelay = 300;
	srand(time(0)); 
	mMaxDepth = 15;

}

void FractalTree::Update(float pElapsed){

	
	mTemp->clear();

	if(!ini){
		ExplosionNode* mHead = new ExplosionNode();
		mHead->Spawned = false;
		mHead->Pos = CalcNewNode(mPos,mPower);
		mHead->mPower = mPower;
		mHead->Radius = 0.0f;
		mHead->Expanding = true;
		mHead->Fini = false;
		mHead->Delay = (mDelay) *Random();
		mHead->SmokeDiv =0.0f;
		mNodes->push_back(mHead);

		ini = true;
	}
	else{
		bool done = true;
		for(int i =0; i < mNodes->size(); i++){
			ExplosionNode* mCurrent = mNodes->at(i);
			if(!mCurrent->Fini){
					done =false;
					
				//Create new explosions
				if(!mCurrent->Spawned){
					mCurrent->Delay += pElapsed;
					int amount = 0;
					if(mCurrent->Delay > mDelay){
						amount = Random() *(mMaxDepth*Random())+1;
						mCurrent->Spawned = true;
					}
					
					ExplosionNode* mNew;
					for(int j = 0; j < amount; j++){
						 mNew = new ExplosionNode();	
						 mNew->mPower = mCurrent->mPower* mSpawnScale;
						 mNew->Radius = 0.0f;
						 mNew->Pos = CalcNewNode(mCurrent->Pos,mNew->mPower);
						 mNew->SmokeDiv =0.0f;
						 mNew->Expanding = true;
						 if(mNew->mPower >mPower*0.3){
							 mNew->Delay = (mDelay) *Random();
							mNew->Fini = false;
							mNew->Spawned = false;
							mTemp->push_back(mNew);
						 } 
					}
				}

				if(mCurrent->Expanding){
					mCurrent->Radius += pElapsed/1000.0f*mExpandRate*mCurrent->mPower;//*mCurrent->mPower;
					if(mCurrent->Radius >= mCurrent->mPower){
						mCurrent->Expanding = false;
						mCurrent->Radius = mCurrent->mPower;
					}
				}else{
					mCurrent->Radius -= pElapsed/1000*mDecayRate*(mCurrent->mPower); //  *(mCurrent->Radius/mCurrent->mPower );
					if(mCurrent->Radius <= 0.0f){
						mCurrent->Radius = 0.0f;
						mCurrent->Fini = true;
					}
				}
			}
			mDone = done;
		}

		for(int a=0; a < mTemp->size(); a++){
			mNodes->push_back(mTemp->at(a));
		}
	}
}


D3DXVECTOR3* FractalTree::CalcNewNode(D3DXVECTOR3* pos, float power){
	D3DXVECTOR3* mRet = new D3DXVECTOR3();
	float neg;
	mRet->x = Random() * power;
	neg = Random();

	if(neg > 0.5){
		mRet->x = mRet->x * -1.0f;
	}

	mRet->x += pos->x ;

	mRet->y = Random() * power;

		neg = Random();

	if(neg > 0.5){
		mRet->y = mRet->y * -1.0f;
	}
	mRet->y += pos->y ;

	mRet->z = Random() * power;
	
	neg = Random();

	if(neg > 0.5){
		mRet->z = mRet->z * -1.0f;
	}
	mRet->z += pos->z ;

	return mRet;
}

void FractalTree::Draw(LPDIRECT3DDEVICE9 d3ddev){
	
	for(int i =0; i < mNodes->size();i++){
		ExplosionNode* mCur = mNodes->at(i);

		mModel->SetPos(mCur->Pos);
		mModel->GetScale()->x = mCur->Radius;
		mModel->GetScale()->y = mCur->Radius;
		mModel->GetScale()->z = mCur->Radius;

		ModelPrimitive* prim = dynamic_cast <ModelPrimitive*> (mModel);

		if(mCur->Expanding){
		prim->GetMaterial()->Diffuse.g =  mCur->Radius/mCur->mPower /2;
		prim->GetMaterial()->Ambient.g = mCur->Radius/mCur->mPower /2;
		prim->GetMaterial()->Specular.g = mCur->Radius/mCur->mPower /2;
		prim->GetMaterial()->Emissive.g = mCur->Radius/mCur->mPower /2;
		prim->GetMaterial()->Diffuse.r =1.0f;
		prim->GetMaterial()->Ambient.r = 1.0f;
		prim->GetMaterial()->Specular.r = 1.0f;
		prim->GetMaterial()->Emissive.r = 1.0f;
		
		prim->GetMaterial()->Diffuse.b =0.0f;
		prim->GetMaterial()->Ambient.b = 0.0f;
		prim->GetMaterial()->Specular.b = 0.0f;
		prim->GetMaterial()->Emissive.b = 0.0f;
		}
		else{
			if(mCur->SmokeDiv ==0.0f){
				mCur->SmokeDiv  = (2*Random()+2);
			}
		
		prim->GetMaterial()->Diffuse.g = mCur->Radius/mCur->mPower /mCur->SmokeDiv ;
		prim->GetMaterial()->Ambient.g =  mCur->Radius/mCur->mPower /mCur->SmokeDiv ;
		prim->GetMaterial()->Specular.g =  mCur->Radius/mCur->mPower/mCur->SmokeDiv ;
		prim->GetMaterial()->Emissive.g =  mCur->Radius/mCur->mPower /mCur->SmokeDiv ;

		prim->GetMaterial()->Diffuse.r =   mCur->Radius/mCur->mPower /mCur->SmokeDiv ;
		prim->GetMaterial()->Ambient.r =  mCur->Radius/mCur->mPower/mCur->SmokeDiv  ;
		prim->GetMaterial()->Specular.r =  mCur->Radius/mCur->mPower/mCur->SmokeDiv ;
		prim->GetMaterial()->Emissive.r = mCur->Radius/mCur->mPower/mCur->SmokeDiv ;

		prim->GetMaterial()->Diffuse.b =   mCur->Radius/mCur->mPower /mCur->SmokeDiv ;
		prim->GetMaterial()->Ambient.b =  mCur->Radius/mCur->mPower /mCur->SmokeDiv ;
		prim->GetMaterial()->Specular.b =  mCur->Radius/mCur->mPower/mCur->SmokeDiv ;
		prim->GetMaterial()->Emissive.b =  mCur->Radius/mCur->mPower/mCur->SmokeDiv ;

		}




		mModel->Draw(d3ddev);
	}
}
